﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Data.Schema.Sql;
using Microsoft.Data.Schema.Extensibility;
using Microsoft.Data.Schema.Tools.DataGenerator;
using System.IO;
using System.Reflection;

namespace DataGenerators
{
    /// <summary>
    /// Generates Countries IDs, names and province names, randomly.
    /// </summary>
    [DatabaseSchemaProviderCompatibility(typeof(SqlDatabaseSchemaProvider))]
    public class CountryGenerator : Generator
    {
        #region private attributes

        static Dictionary<int, string> _countries = GetCountries();

        static Dictionary<int, List<string>> _provinces = GetProvinces();

        Random _random;

        #endregion

        /// <summary>
        /// Creates a new instance of <see cref="CountryGenerator"/>
        /// </summary>
        public CountryGenerator()
        {
            _random = new Random(this.Seed);
        }

        #region private methods

        private static Dictionary<int, string> GetCountries()
        {
            Dictionary<int, string> result = new Dictionary<int, string>();

            using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("DataGenerators.DataFiles.countries.txt"))
            using (StreamReader reader = new StreamReader(stream))
            {
                string countries = reader.ReadToEnd();

                foreach (string country in countries.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                {
                    string[] data = country.Split(',');
                    result.Add(int.Parse(data[0]), data[1]);
                }
            }
            return result;
        }

        private static Dictionary<int, List<string>> GetProvinces()
        {
            Dictionary<int, List<string>> result = new Dictionary<int, List<string>>();

            using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("DataGenerators.DataFiles.provinces.txt"))
            using (StreamReader reader = new StreamReader(stream))
            {
                string provinces = reader.ReadToEnd();

                foreach (string province in provinces.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                {
                    string[] data = province.Split(',');
                    int country = int.Parse(data[0]);
                    if (!result.ContainsKey(country))
                        result.Add(country, new List<string>());

                    result[country].Add(data[1]);
                }
            }
            return result;
        }

        #endregion

        #region overrides

        /// <summary>
        /// Generates the next value according to the data generation algorithm.
        /// </summary>
        protected override void OnGenerateNextValues()
        {
            int r = _random.Next(_countries.Keys.Count);

            Id = _countries.Keys.ElementAt(r);
            CountryName = _countries[Id];
            ProvinceName = _provinces[Id][_random.Next(_provinces[Id].Count)];
        }

        /// <summary>
        ///     Generates the next set of values for a data row. 
        /// </summary>
        protected override void OnNextValues()
        {
            OnGenerateNextValues();
        }


        /// <summary>
        /// Initializes the generator.
        /// </summary>
        /// <param name="initInfo">
        /// A Microsoft.Data.Schema.Tools.DataGenerator.GeneratorInit object containing
        /// run-time configuration information, such as the database connection string.
        /// Also contains shared instancing information.
        /// </param>
        protected override void OnInitialize(GeneratorInit initInfo)
        {
            _random = new Random(this.Seed);

            base.OnInitialize(initInfo);
        }

        #endregion

        #region public Properties

        /// <summary>
        /// Gets the random generated Country ID from GeoNames.org
        /// </summary>
        [Output(Name = "Id Pais", Description = "Devuelve el ID del pais segun GeoNames.org.")]
        public int Id { get; private set; }

        /// <summary>
        /// Gets the random generate Counrtry Name.
        /// </summary>
        [Output(Name = "Pais", Description = "Devuelve el nombre del pais en ingles.")]
        public string CountryName { get; private set; }

        /// <summary>
        /// Gets the random  generated Province Name
        /// </summary>
        [Output(Name = "Provincia", Description = "Devuelve el nombre de la provincia.")]
        public string ProvinceName { get; private set; }

        #endregion
    }
}
